﻿
//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

#include "CmdSnapModuleEntry.h"
#include "IControl.h"
#include "StringUtil.h"
#include "IRibbonGroup.h"
#include "IGroupHandler.h"
#include "IActionManager.h"
#include "ILabelDefinition.h"
#include "IComboBoxHandler.h"
#include "GcmpCommandState.h"
#include "ILineEditHandler.h"
#include "IComboBoxEventArgs.h"
#include "ILineEditEventArgs.h"
#include "UiDocumentViewUtils.h"
#include "ILineEditDefinition.h"
#include "IComboBoxDefinition.h"
#include "IRibbonContextualPage.h"
#include "ICommandButtonDefinition.h"
#include "ICheckBoxGroupDefinition.h"
#include "IControlDefinitionLibrary.h"

#include <shellapi.h>
#include "UiBuilder.h"
#include "SnapFilterDlg.h"
#include "CommandRegister.h"
#include "SampleUIUtils.h"
#include "PickSnapCommandIds.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h" 

/// 本文件是界面实现的辅助类，不包含GDMP API的演示内容

using namespace Sample;
using namespace gcmp;

// 工作平面
#define ID_CMD_GBMP_SETUP_WORK_PLANE              L"gbmpSetupWorkPlaneCmd"
#define ID_CMD_GBMP_SETUP_WORK_PLANE_BY_PICK      L"gbmpSetupWorkPlaneByPickCmd"
#define ID_CMD_SHOW_HIDE_WORK_PLANE               L"gmShowHideWorkPlaneCmd"
#define ID_CMD_GBMP_MODIFY                        L"gbmpModifyCmd"

#pragma region 各种Ribbon控件的状态控制

// 捕捉API下拉菜单
class SnapComboBoxHandler : public IComboBoxHandler
{

public:
    SnapComboBoxHandler(std::wstring id)
    {
        m_id = id;
    }

    virtual bool IsVisible() const override { return true; }

    virtual bool IsEnabled()const override { return true; }

    static void UpdateComboBox(IRibbonGroup* pRibbonGroup, SnapMethod pickMethod)
    {
        IControl* pControl1 = pRibbonGroup->GetControl(ID_COMBOBOX_SNAP_PLANE);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pControl1, L"pControl1为空",L"GDMP",L"2023-12-30");
        IComboBoxDefinition* pComboBoxSnapPlaneDefinition = dynamic_cast<IComboBoxDefinition*>(pControl1->GetControlDefinition());
        DBG_WARN_AND_RETURN_VOID_UNLESS(pComboBoxSnapPlaneDefinition, L"pComboBoxSnapPlaneDefinition为空",L"GDMP",L"2023-12-30");

        IControl* pControl2 = pRibbonGroup->GetControl(ID_COMBOBOX_PICK_POINT_TYPE);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pControl2, L"pControl2为空",L"GDMP",L"2023-12-30");
        IComboBoxDefinition* pComboBoxSnapPointTypeDefinition = dynamic_cast<IComboBoxDefinition*>(pControl2->GetControlDefinition());
        DBG_WARN_AND_RETURN_VOID_UNLESS(pComboBoxSnapPointTypeDefinition, L"pComboBoxSnapPointTypeDefinition为空",L"GDMP",L"2023-12-30");

        if (pickMethod == SnapMethod::Snapper)
        {
            pComboBoxSnapPlaneDefinition->SetEnabled(false);
            pComboBoxSnapPointTypeDefinition->SetEnabled(false);
        }
        else if (pickMethod == SnapMethod::IPickPointAction)
        {
            pComboBoxSnapPlaneDefinition->SetEnabled(true);
            pComboBoxSnapPointTypeDefinition->SetEnabled(true);
        }
        else
        {
            pComboBoxSnapPlaneDefinition->SetEnabled(true);
            pComboBoxSnapPointTypeDefinition->SetEnabled(true);
        }
    }

    static void UpdateCheckBoxGroup(ICheckBoxGroupDefinition* pCheckBoxGroupDefinition, SnapMethod snapMethod)
    {
        if (snapMethod == SnapMethod::IPickPointAction)
        {
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_CUSTOMIZE_CURSOR, true);
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_ROTATE_COORDINATE, true);
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_USE_COORDINATE_INPUT, true);
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_SET_XY_SNAP_PLANE, true);
        }
        else if (snapMethod == SnapMethod::Snapper)
        {
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_CUSTOMIZE_CURSOR, true);
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_ROTATE_COORDINATE, false);
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_USE_COORDINATE_INPUT, false);
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_SET_XY_SNAP_PLANE, false);
        }
        else
        {
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_CUSTOMIZE_CURSOR, false);
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_ROTATE_COORDINATE, true);
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_USE_COORDINATE_INPUT, false);
            pCheckBoxGroupDefinition->SetEnabled(ID_CHECKBOX_SET_XY_SNAP_PLANE, true);
        }
    }

    virtual void On(IComboBoxEventArgs* pArgs) override
    {
        // 根据捕捉API接口设置checkbox的可见性
        SnapMethod snapMethod = pArgs->GetCurrentData().cast<SnapMethod>();
        if (IRibbonGroup* pRibbonGroup = CmdSnapModuleEntry::GetRibbonGroup())
        {
            SnapMethod snapMethod = CmdSnapModuleEntry::GetSnapMethod();
            SnapFilterDlg* pSnapFilterDlg = SnapFilterDlg::Get();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pSnapFilterDlg, L"pSnapFilterDlg为空",L"GDMP",L"2023-12-30");
            pSnapFilterDlg->SetSnapMethod(snapMethod);

            UpdateComboBox(pRibbonGroup, snapMethod);

            IControl* pControl = pRibbonGroup->GetControl(ID_CHECKBOX_GROUP_SNAP);
            DBG_WARN_AND_RETURN_VOID_UNLESS(pControl, L"pControl为空",L"GDMP",L"2023-12-30");
            ICheckBoxGroupDefinition* pCheckBoxGroupDefinition = dynamic_cast<ICheckBoxGroupDefinition*>(pControl->GetControlDefinition());
            DBG_WARN_AND_RETURN_VOID_UNLESS(pCheckBoxGroupDefinition, L"pCheckBoxGroupDefinition为空",L"GDMP",L"2023-12-30");

            UpdateCheckBoxGroup(pCheckBoxGroupDefinition, snapMethod);

            for (auto itor : pRibbonGroup->GetAllControls())
            {
                DBG_WARN_AND_RETURN_VOID_UNLESS(itor, L"itor为空",L"GDMP",L"2023-12-30");
                itor->UpdateStatus();
            }
        }

        ICommandManager* pCommandManager = ICommandManager::Get();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pCommandManager, L"pCommandManager为空",L"GDMP",L"2023-12-30");
        IActionManager::Reset();
        pCommandManager->SendCommand(ID_CMD_GBMP_MODIFY);
    }
private:
    std::wstring m_id;
};

// 捕捉像素容差文本框
class SnapLineEditHandler : public ILineEditHandler
{

public:
    virtual bool IsVisible() const override { return true; }

    virtual bool IsEnabled() const override { return true; }

    virtual void On(ILineEditEventArgs* pArgs) override
    {
        bool ok;
        int num = StringUtil::ToNumber<int>(pArgs->GetText(), &ok);
        if (!ok || num <= 0)
        {
            if (IRibbonGroup* pRibbonGroup = CmdSnapModuleEntry::GetRibbonGroup())
            {
                IControl* pControl = pRibbonGroup->GetControl(ID_LINE_SNAP_TOLERANCE);
                DBG_WARN_AND_RETURN_VOID_UNLESS(pControl, L"pControl为空",L"GDMP",L"2023-12-30");
                ILineEditDefinition* pCheckBoxGroupDefinition = dynamic_cast<ILineEditDefinition*>(pControl->GetControlDefinition());
                DBG_WARN_AND_RETURN_VOID_UNLESS(pCheckBoxGroupDefinition, L"pCheckBoxGroupDefinition为空",L"GDMP",L"2023-12-30");
                pCheckBoxGroupDefinition->SetText(L"8");
            }
        }
    }
};

// 整个捕捉模块Ribbon可见性控制
class SnapGroupHandler : public IGroupHandler
{

public:
    virtual bool IsVisible() const override
    {
        return GcmpCommandState::IsInDocumentEnvironment();
    }
};
#pragma endregion 各种Ribbon控件的状态控制

#pragma  region CmdSnapHelp
REGISTER_COMMAND(CmdSnapHelp)

CmdSnapHelp::CmdSnapHelp() : CommandBase(ID_CMD_SNAP_HELP) {}
CmdSnapHelp::~CmdSnapHelp() {}

gcmp::OwnerPtr<gcmp::IAction> CmdSnapHelp::ExecuteCommand(const gcmp::CommandParameters& cmdParams)
{
    ShellExecute(NULL, L"open", L"https://developer.glodon.com/docs/gdmp/24.0.0305.0/cppdev/1l4e134j", NULL, NULL, SW_SHOWNORMAL);
    return nullptr;
}

bool CmdSnapHelp::IsEnabled() const
{
    return GcmpCommandState::IsInDocumentEnvironment();
}

bool CmdSnapHelp::IsVisible() const
{
    return GcmpCommandState::IsInDocumentEnvironment();
}
#pragma endregion

#pragma region CmdSnapModuleEntry
REGISTER_COMMAND(CmdSnapModuleEntry)

CmdSnapModuleEntry::CmdSnapModuleEntry() : CommandBase(ID_CMD_SNAP_ENTRY) {}
CmdSnapModuleEntry::~CmdSnapModuleEntry() {}

bool CmdSnapModuleEntry::IsEnabled() const
{
    return GcmpCommandState::IsInDocumentEnvironment();
}

bool CmdSnapModuleEntry::IsVisible() const
{
    return GcmpCommandState::IsInDocumentEnvironment();
}

const SnapMethod Sample::CmdSnapModuleEntry::GetSnapMethod()
{
    IRibbonGroup* pRibbonGroup = GetRibbonGroup();

    if (!pRibbonGroup) return SnapMethod::Unknow;
    IControl* pControl = pRibbonGroup->GetControl(ID_COMBOBOX_SNAP_METHOD);
    DBG_WARN_AND_RETURN_UNLESS(pControl, SnapMethod::Unknow, L"pControl为空",L"GDMP",L"2023-12-30");
    IComboBoxDefinition* pComboBoxSnapMethodDefinition = dynamic_cast<IComboBoxDefinition*>(pControl->GetControlDefinition());
    DBG_WARN_AND_RETURN_UNLESS(pComboBoxSnapMethodDefinition, SnapMethod::Unknow, L"pComboBoxSnapMethodDefinition为空",L"GDMP",L"2023-12-30");
    Any userData = pComboBoxSnapMethodDefinition->GetCurrentData();
    return userData.cast<SnapMethod>();
}

const bool Sample::CmdSnapModuleEntry::DoCustomizeCursor()
{
    return GetCheckboxValue(ID_CHECKBOX_GROUP_SNAP, ID_CHECKBOX_CUSTOMIZE_CURSOR);
}

const bool Sample::CmdSnapModuleEntry::DoRotateCoordinate()
{
    return GetCheckboxValue(ID_CHECKBOX_GROUP_SNAP, ID_CHECKBOX_ROTATE_COORDINATE);
}

const bool Sample::CmdSnapModuleEntry::DoUseCoordinateInput()
{
    return GetCheckboxValue(ID_CHECKBOX_GROUP_SNAP, ID_CHECKBOX_USE_COORDINATE_INPUT);
}

const bool Sample::CmdSnapModuleEntry::DoSetXYPlaneAsSnapPlane()
{
    return GetCheckboxValue(ID_CHECKBOX_GROUP_SNAP, ID_CHECKBOX_SET_XY_SNAP_PLANE);
}

const int Sample::CmdSnapModuleEntry::GetModelLinePointCount()
{
    if (IRibbonGroup* pRibbonGroup = GetRibbonGroup())
    {
        IControl* pControl = pRibbonGroup->GetControl(ID_MODEL_LINE_POINT_COUNT);
        DBG_WARN_AND_RETURN_UNLESS(pControl, 1, L"pControl为空",L"GDMP",L"2023-12-30");
        ILineEditDefinition* pCheckBoxGroupDefinition = dynamic_cast<ILineEditDefinition*>(pControl->GetControlDefinition());
        DBG_WARN_AND_RETURN_UNLESS(pCheckBoxGroupDefinition, 8, L"pCheckBoxGroupDefinition为空",L"GDMP",L"2023-12-30");
        bool ok;
        int tolearance = StringUtil::ToNumber<int>(pCheckBoxGroupDefinition->GetText(), &ok);
        if (ok)
        {
            return tolearance;
        }
    }
    return 1;
}

const int Sample::CmdSnapModuleEntry::GetTolerance()
{
    if (IRibbonGroup* pRibbonGroup = GetRibbonGroup())
    {
        IControl* pControl = pRibbonGroup->GetControl(ID_LINE_SNAP_TOLERANCE);
        DBG_WARN_AND_RETURN_UNLESS(pControl, 8, L"pControl为空",L"GDMP",L"2023-12-30");
        ILineEditDefinition* pCheckBoxGroupDefinition = dynamic_cast<ILineEditDefinition*>(pControl->GetControlDefinition());
        DBG_WARN_AND_RETURN_UNLESS(pCheckBoxGroupDefinition, 8, L"pCheckBoxGroupDefinition为空",L"GDMP",L"2023-12-30");
        bool ok;
        int tolearance = StringUtil::ToNumber<int>(pCheckBoxGroupDefinition->GetText(), &ok);
        if (ok)
        {
            return tolearance;
        }
    }
    return 8;
}

const gcmp::PickPointExchangeData::SnapPlaneType Sample::CmdSnapModuleEntry::GetSnapPlaneType()
{
    IRibbonGroup* pRibbonGroup = GetRibbonGroup();

    if (!pRibbonGroup) return PickPointExchangeData::SnapPlaneType::WorkPlane;
    IControl* pControl = pRibbonGroup->GetControl(ID_COMBOBOX_SNAP_PLANE);
    DBG_WARN_AND_RETURN_UNLESS(pControl, PickPointExchangeData::SnapPlaneType::WorkPlane, L"pControl为空",L"GDMP",L"2023-12-30");
    IComboBoxDefinition* pComboBoxSnapPlaneDefinition = dynamic_cast<IComboBoxDefinition*>(pControl->GetControlDefinition());
    DBG_WARN_AND_RETURN_UNLESS(pComboBoxSnapPlaneDefinition, PickPointExchangeData::SnapPlaneType::WorkPlane, L"pComboBoxSnapPlaneDefinition为空",L"GDMP",L"2023-12-30");
    Any userData = pComboBoxSnapPlaneDefinition->GetCurrentData();
    return userData.cast<PickPointExchangeData::SnapPlaneType>();
}

const gcmp::InteractivePicker::SnapPlaneType Sample::CmdSnapModuleEntry::GetPickerSnapPlaneType()
{
    int index = (int)GetSnapPlaneType();
    return (gcmp::InteractivePicker::SnapPlaneType)index;
}

const gcmp::PickPointExchangeData::PickPointType Sample::CmdSnapModuleEntry::GetPickPointType()
{
    IRibbonGroup* pRibbonGroup = GetRibbonGroup();

    if (!pRibbonGroup) return PickPointExchangeData::PickPointType::TwoDimensionPoint;
    IControl* pControl = pRibbonGroup->GetControl(ID_COMBOBOX_PICK_POINT_TYPE);
    DBG_WARN_AND_RETURN_UNLESS(pControl, PickPointExchangeData::PickPointType::TwoDimensionPoint, L"pControl为空",L"GDMP",L"2023-12-30");
    IComboBoxDefinition* pComboBoxSnapPlaneDefinition = dynamic_cast<IComboBoxDefinition*>(pControl->GetControlDefinition());
    DBG_WARN_AND_RETURN_UNLESS(pComboBoxSnapPlaneDefinition, PickPointExchangeData::PickPointType::TwoDimensionPoint, L"pComboBoxSnapPlaneDefinition为空",L"GDMP",L"2023-12-30");
    Any userData = pComboBoxSnapPlaneDefinition->GetCurrentData();
    return userData.cast<PickPointExchangeData::PickPointType>();
}

const gcmp::InteractivePicker::PickPointType Sample::CmdSnapModuleEntry::GetPickerPickPointType()
{
    int index = (int)GetPickPointType();
    return (gcmp::InteractivePicker::PickPointType)index;
}

IRibbonGroup* Sample::CmdSnapModuleEntry::GetRibbonGroup()
{
    ModuleUIUtils* pModuleUIUtils = ModuleUIUtils::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModuleUIUtils, L"pModuleUIUtils为空",L"GDMP",L"2023-12-30");
    return SampleUIUtils::FindGroup(ID_PAGE_MODULE, ID_GROUP_MODULE_SNAP_CONTEXT);
}

const bool Sample::CmdSnapModuleEntry::GetCheckboxValue(std::wstring checkboxGroupId, std::wstring checkboxId)
{
    if (IRibbonGroup* pRibbonGroup = GetRibbonGroup())
    {
        IControl* pControl = pRibbonGroup->GetControl(checkboxGroupId);
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pControl, L"pControl为空",L"GDMP",L"2023-12-30");
        ICheckBoxGroupDefinition* pCheckBoxGroupDefinition = dynamic_cast<ICheckBoxGroupDefinition*>(pControl->GetControlDefinition());
        DBG_WARN_AND_RETURN_FALSE_UNLESS(pCheckBoxGroupDefinition, L"pCheckBoxGroupDefinition为空",L"GDMP",L"2023-12-30");
        bool ok;
        return pCheckBoxGroupDefinition->GetCheckState(checkboxId, &ok) == CheckState::Checked;
    }
    return false;
}

OwnerPtr<IAction> CmdSnapModuleEntry::ExecuteCommand(const CommandParameters& cmdParams)
{
    ModuleUIUtils::Get()->RemoveModuleUI();
    UiBuilder::CleanContextUI();
    if (SnapFilterDlg* dlg = SnapFilterDlg::Get())
    {
        dlg->ShowDock();
    }
    else
    {
        SnapFilterDlg::Create();
    }

    if (GetRibbonGroup())
    {
        return nullptr;
    }

    std::wstring groupName = L"捕捉模块示例";

    OwnerPtr<IRibbonGroup> opSnapGroup = IRibbonGroup::Create(ID_GROUP_MODULE_SNAP_CONTEXT, GBMP_TR(groupName));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSnapGroup, L"opSnapGroup为空",L"GDMP",L"2023-12-30");
    opSnapGroup->SetGroupHandler(NEW_AS_OWNER_PTR(SnapGroupHandler));

    OwnerPtr<IComboBoxDefinition> opComboBoxSnapMethodDefinition =
        IComboBoxDefinition::Create(ID_COMBOBOX_SNAP_METHOD, L"捕捉API:");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opComboBoxSnapMethodDefinition, L"opComboBoxSnapMethodDefinition为空",L"GDMP",L"2023-12-30");
    opComboBoxSnapMethodDefinition->AddItem(L"Action捕捉", SnapMethod::IPickPointAction);
    opComboBoxSnapMethodDefinition->AddItem(L"Snapper捕捉", SnapMethod::Snapper);
    opComboBoxSnapMethodDefinition->AddItem(L"InteractivePicker", SnapMethod::InteractivePicker);
    OwnerPtr<IComboBoxHandler> opComboBoxHandler = NEW_AS_OWNER_PTR(SnapComboBoxHandler, ID_COMBOBOX_SNAP_METHOD);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opComboBoxHandler, L"opComboBoxHandler为空",L"GDMP",L"2023-12-30");
    opComboBoxSnapMethodDefinition->SetControlHandler(TransferOwnership(opComboBoxHandler));
    opSnapGroup->AddComboBox(TransferOwnership(opComboBoxSnapMethodDefinition));

    OwnerPtr<ICommandButtonDefinition> opSnapWithActionDefinition =
        ICommandButtonDefinition::Create(ID_CMD_SNAP_WITH_ACTION, GBMP_TR(L"Action捕捉"),
            GBMP_TR(L"用ISnapPointAction捕捉图元，可以在右侧过滤树和菜单中设置捕捉API常用接口"),
            ID_CMD_SNAP_WITH_ACTION, L":/images/Module/PickSnap/snap.png");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSnapWithActionDefinition, L"opSnapWithActionDefinition为空",L"GDMP",L"2023-12-30");
    opSnapGroup->AddButton(TransferOwnership(opSnapWithActionDefinition));

    OwnerPtr<ICommandButtonDefinition> opSnapWithSnapperDefinition =
        ICommandButtonDefinition::Create(ID_CMD_SNAP_WITH_SNAPPER, GBMP_TR(L"Snapper捕捉"),
            GBMP_TR(L"用Snapper捕捉图元，可以在右侧过滤树和菜单中设置捕捉API常用接口，SnapPlane使用当前视图的工作平面"),
            ID_CMD_SNAP_WITH_SNAPPER, L":/images/Module/PickSnap/snap.png");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSnapWithSnapperDefinition, L"opSnapWithSnapperDefinition为空",L"GDMP",L"2023-12-30");
    opSnapGroup->AddButton(TransferOwnership(opSnapWithSnapperDefinition));

    OwnerPtr<ICommandButtonDefinition> opSnapWithInteractivePickerDefinition =
        ICommandButtonDefinition::Create(ID_CMD_SNAP_WITH_INTERACTIVE_PICKER, GBMP_TR(L"InteractivePicker捕捉"),
            GBMP_TR(L"用InteractivePicker捕捉图元，可以在右侧过滤树和菜单中设置捕捉API常用接口"),
            ID_CMD_SNAP_WITH_INTERACTIVE_PICKER, L":/images/Module/PickSnap/snap.png");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSnapWithInteractivePickerDefinition, L"opSnapWithInteractivePickerDefinition为空",L"GDMP",L"2023-12-30");
    opSnapGroup->AddButton(TransferOwnership(opSnapWithInteractivePickerDefinition));

    OwnerPtr<IComboBoxDefinition> opComboBoxSnapPlaneDefinition =
        IComboBoxDefinition::Create(ID_COMBOBOX_SNAP_PLANE, L"SnapPlaneType");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opComboBoxSnapPlaneDefinition, L"opComboBoxSnapPlaneDefinition为空",L"GDMP",L"2023-12-30");
    opComboBoxSnapPlaneDefinition->AddItem(L"WorkPlane", PickPointExchangeData::SnapPlaneType::WorkPlane);
    opComboBoxSnapPlaneDefinition->AddItem(L"SnapPlane", PickPointExchangeData::SnapPlaneType::SnapPlane);
    opComboBoxSnapPlaneDefinition->AddItem(L"FirstPointPlane", PickPointExchangeData::SnapPlaneType::FirstPointPlane);
    opSnapGroup->AddComboBox(TransferOwnership(opComboBoxSnapPlaneDefinition));

    OwnerPtr<IComboBoxDefinition> opComboBoxPickPointTypeDefinition =
        IComboBoxDefinition::Create(ID_COMBOBOX_PICK_POINT_TYPE, L"PickPointType");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opComboBoxPickPointTypeDefinition, L"opComboBoxPickPointTypeDefinition为空",L"GDMP",L"2023-12-30");
    opComboBoxPickPointTypeDefinition->AddItem(L"TwoDimensionPoint", PickPointExchangeData::PickPointType::TwoDimensionPoint);
    opComboBoxPickPointTypeDefinition->AddItem(L"ThreeDimensionPoint", PickPointExchangeData::PickPointType::ThreeDimensionPoint);
    opSnapGroup->AddComboBox(TransferOwnership(opComboBoxPickPointTypeDefinition));

    OwnerPtr<ILineEditDefinition> opToleranceILineDefinition =
        ILineEditDefinition::Create(ID_LINE_SNAP_TOLERANCE, L"捕捉像素容差", LineEditInputType::InputInt);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opToleranceILineDefinition, L"opToleranceILineDefinition为空",L"GDMP",L"2023-12-30");
    opToleranceILineDefinition->SetControlHandler(NEW_AS_OWNER_PTR(SnapLineEditHandler));
    opToleranceILineDefinition->SetText(L"8");
    opSnapGroup->AddLineEdit(TransferOwnership(opToleranceILineDefinition)); 

    OwnerPtr<ICheckBoxGroupDefinition> opCheckBoxGroupDefinition = ICheckBoxGroupDefinition::Create(ID_CHECKBOX_GROUP_SNAP, L"捕捉选项");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opCheckBoxGroupDefinition, L"opCheckBoxGroupDefinition为空",L"GDMP",L"2023-12-30");
    opCheckBoxGroupDefinition->AddCheckBox(ID_CHECKBOX_CUSTOMIZE_CURSOR, L"自定义光标", L"捕捉中使用自定义的鼠标光标（每次捕捉开始前设置）", CheckState::Unchecked);
    opCheckBoxGroupDefinition->AddCheckBox(ID_CHECKBOX_USE_COORDINATE_INPUT, L"可以输入坐标", L"显示坐标输入控件，可以直接输入坐标绘制（每次捕捉开始前设置）", CheckState::Unchecked);
    opCheckBoxGroupDefinition->AddCheckBox(ID_CHECKBOX_ROTATE_COORDINATE, L"旋转Coordinate", L"旋转SnapPlane的Coordinate的X轴到上一根线的方向。如果设置零点的XY平面为SnapPlane，本选项不起作用（每次捕捉开始前设置）", CheckState::Unchecked); 
    opCheckBoxGroupDefinition->AddCheckBox(ID_CHECKBOX_SET_XY_SNAP_PLANE, L"设置XY平面为SnapPlane", L"设置零点的XY平面为ISnapContext的SnapPlane，否则使用当前视图的工作平面（每次捕捉开始前设置）", CheckState::Unchecked);
    SnapComboBoxHandler::UpdateCheckBoxGroup(opCheckBoxGroupDefinition.get(), SnapMethod::IPickPointAction);
    opSnapGroup->AddCheckBoxGroup(TransferOwnership(opCheckBoxGroupDefinition));

    OwnerPtr<ILineEditDefinition> opModelLinePointCountDefinition =
        ILineEditDefinition::Create(ID_MODEL_LINE_POINT_COUNT, L"模型线等分捕捉点", LineEditInputType::InputInt);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opModelLinePointCountDefinition, L"opModelLinePointCountDefinition为空",L"GDMP",L"2023-12-30");
    opModelLinePointCountDefinition->SetControlHandler(NEW_AS_OWNER_PTR(SnapLineEditHandler));
    opModelLinePointCountDefinition->SetText(L"1");
    opSnapGroup->AddLineEdit(TransferOwnership(opModelLinePointCountDefinition));

    OwnerPtr<ICommandButtonDefinition> opPickCreateModelDefinition =
        ICommandButtonDefinition::Create(ID_CMD_PICK_CREATE_MODEL, GBMP_TR(L"创建测试模型"),
            GBMP_TR(L"创建各种不同性质的模型，这些模型在捕捉捕捉API接口设置不同选项的表现不同"),
            ID_CMD_PICK_CREATE_MODEL, L":/images/Module/Common/model.png");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opPickCreateModelDefinition, L"opPickCreateModelDefinition为空",L"GDMP",L"2023-12-30");
    opSnapGroup->AddButton(TransferOwnership(opPickCreateModelDefinition));

    OwnerPtr<ICommandButtonDefinition> opSetWorkPlaneDefinition =
        ICommandButtonDefinition::Create(ID_CMD_GBMP_SETUP_WORK_PLANE_BY_PICK, GBMP_TR(L"设置工作平面"),
            GBMP_TR(L"捕捉平面，作为当前视图的工作平面。捕捉中也会使用该工作平面"),
            ID_CMD_GBMP_SETUP_WORK_PLANE_BY_PICK, L":/images/Module/Common/work_plane.png");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opSetWorkPlaneDefinition, L"opSetWorkPlaneDefinition为空",L"GDMP",L"2023-12-30");
    opSnapGroup->AddButton(TransferOwnership(opSetWorkPlaneDefinition));

    OwnerPtr<ICommandButtonDefinition> opDisplayWorkPlaneDefinition =
        ICommandButtonDefinition::Create(ID_CMD_SHOW_HIDE_WORK_PLANE, GBMP_TR(L"打开/关闭工作平面"),
            GBMP_TR(L"打开/关闭当前视图的工作平面。捕捉中也会使用该工作平面"),
            ID_CMD_SHOW_HIDE_WORK_PLANE, L":/images/Module/Common/workplane_off.png");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opDisplayWorkPlaneDefinition, L"opDisplayWorkPlaneDefinition为空",L"GDMP",L"2023-12-30");
    opSnapGroup->AddButton(TransferOwnership(opDisplayWorkPlaneDefinition));

    OwnerPtr<ICommandButtonDefinition> opHelpDefinition =
        ICommandButtonDefinition::Create(ID_CMD_SNAP_HELP, GBMP_TR(L"帮助"), GBMP_TR(L"打开GDMP在线帮助网站"),
            ID_CMD_SNAP_HELP, L":/images/Module/Common/Help.png");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opHelpDefinition, L"opHelpDefinition为空",L"GDMP",L"2023-12-30");
    opSnapGroup->AddButton(TransferOwnership(opHelpDefinition));

    SnapComboBoxHandler::UpdateComboBox(opSnapGroup.get(), SnapMethod::IPickPointAction);

    ModuleUIUtils::Get()->SetupModuleUI(TransferOwnership(opSnapGroup), groupName);

    return nullptr;
}

#pragma endregion CmdSnapModuleEntry

